package org.spp.batchedAccess;

import org.spp.voronoi.Centroid;
import org.spp.utilities.comparators.DivScoreComparator;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

/**
 * MMR.java
 * @author Ilio Catallo, Eleonora Ciceri
 * @version 1.0
 * 
 * Description: the class implements the MMR algorithm
 * 
 * Date: Jul 16, 2011
 */
public class MMR {

    /**
     * Constructor for the class MMR
     */
    public MMR() {
        
    }
   
    /**
     * Methods that executes the algorithm 
     * @param K
     * @param invoker
     * @param lambda
     * @return resultSet
     */
    public List<Centroid> run(Integer K, Invoker invoker, Double lambda){        
        // Variables
        List<Centroid> selectedObjs = new ArrayList<Centroid>();
        List<Centroid> objects = invoker.getObjects();
        
        // The first object is choosen as the best object in term of score
        Centroid nextSelectedObj = invoker.pullObjectByScore(0);

        for (int k = 2; k <= K; k++){   
            
            // Create the list of all the not selected objects
            selectedObjs.add(nextSelectedObj);
            List<Centroid> notSelectedObjs = new ArrayList<Centroid>();
            notSelectedObjs.addAll(objects);
            notSelectedObjs.removeAll(selectedObjs);
                        
            // Compute the diversity weighted score of each not selected object
            for (Centroid notSelectedObj: notSelectedObjs)
                notSelectedObj.computeDivScore(lambda, selectedObjs);
         
            // Order the object by diversity weighted score
            TreeSet notSelectedObjsSet = new TreeSet(new DivScoreComparator());
            notSelectedObjsSet.addAll(notSelectedObjs);
            
            // Choose the next object to be put in result set 
            // as the best object in term of diversity weighted score
            nextSelectedObj = (Centroid)notSelectedObjsSet.first();            
        }     
        
        // Put in the result set the last object
        selectedObjs.add(nextSelectedObj);
        return selectedObjs;        
    }
    
}
